package fr.alma.trajectory.rendering;

import java.awt.event.KeyEvent;

public class Camera
{
	public boolean vueSolide;
	public boolean squelettemode;
	private boolean lightMove;
	private boolean lightSelect;
	private int lightSelected;
	private boolean activateLight;
	
    private double xPos;
    private double yPos;
    private double zPos;
    
    private double xLPos;
    private double yLPos;
    private double zLPos;
    
    private double pitch;
    private double yaw;
    
    public Camera()
    {
        init();
        
        lightSelected = -1;
    }
    
    public void init()
    {
        xPos = 0;
        yPos = 0;
        zPos = 0;
        
        xLPos = 0;
        yLPos = 0;
        zLPos = 10;
        
        yawLeft(2.5);
        pitchDown(0.3);
        moveForward(-10);
        look(10);
        
    }
    
    public Camera(double xPos, double yPos, double zPos, double xLPos, double yLPos, double zLPos)
    {
        this.xPos = xPos;
        this.yPos = yPos;
        this.zPos = zPos;
        
        this.xLPos = xLPos;
        this.yLPos = yLPos;
        this.zLPos = zLPos;
        
        vueSolide = true;
    }
    
    public void setPitch(double pitch)
    {
    	this.pitch = pitch;
    }
    
    public void setYaw(double yaw)
    {
    	this.yaw = yaw;
    }

    public void updatePosition(double xPos, double yPos, double zPos)
    {
        this.xPos = xPos;
        this.yPos = yPos;
        this.zPos = zPos;
    }
    
    public void lookPosition(double xLPos, double yLPos, double zLPos)
    {
        this.xLPos = xLPos;
        this.yLPos = yLPos;
        this.zLPos = zLPos;
    }

    
    // Moves the entity forward according to its pitch and yaw and the magnitude.
    
    public void moveForward(double magnitude)
    {
        double xCurrent = this.xPos;
        double yCurrent = this.yPos;
        double zCurrent = this.zPos;
        
        // Spherical coordinates maths
        double xMovement = magnitude * Math.cos(pitch) * Math.cos(yaw); 
        double yMovement = magnitude * Math.sin(pitch);
        double zMovement = magnitude * Math.cos(pitch) * Math.sin(yaw);
              
        double xNew = xCurrent + xMovement;
        double yNew = yCurrent + yMovement;
        double zNew = zCurrent + zMovement;
        
        updatePosition(xNew, yNew, zNew);
    }
    
    public void strafeLeft(double magnitude)
    {
        double pitchTemp = pitch;
        pitch = 0;
        yaw = yaw - (0.5 * Math.PI);
        moveForward(magnitude);

        pitch = pitchTemp;
        yaw = yaw + (0.5 * Math.PI);
    }
    
    public void strafeRight(double magnitude)
    {
        double pitchTemp = pitch;
        pitch = 0;

        yaw = yaw + (0.5 * Math.PI);
        moveForward(magnitude);
        yaw = yaw - (0.5 * Math.PI);

        pitch = pitchTemp;
    }
    
    
    public void look(double distanceAway)
    {
        if(pitch > 1.0)
        pitch = 0.99;
        
        if(pitch < -1.0)
        pitch = -0.99;
         
        moveForward(10);
        
        double xLook = xPos;
        double yLook = yPos;
        double zLook = zPos;
        
        moveForward(-10);
        
        lookPosition(xLook, yLook, zLook);
    }
           
    
    /* -------Get commands--------- */
    
    public double getXPos()
    {
        return xPos;
    }
    
    public double getYPos()
    {
        return yPos;
    }
    
    public double getZPos()
    {
        return zPos;
    }
    
    public double getXLPos()
    {
        return xLPos;
    }
    
    public double getYLPos()
    {
        return yLPos;
    }
    
    public double getZLPos()
    {
        return zLPos;
    }
    
    public double getPitch()
    {
        return pitch;
    }
    
    public double getYaw()
    {
        return yaw;
    }
    
    /* --------------------------- */
    
    /* -------------- Pitch and Yaw commands --------------- */
    
    public void pitchUp(double amount)
    {
        this.pitch += amount;
    }
    
    public void pitchDown(double amount)
    {
        this.pitch -= amount;
    }
    
    public void yawRight(double amount)
    {
        this.yaw += amount;
    }
    
    public void yawLeft(double amount)
    {
        this.yaw -= amount;
    }
    
    /* ---------------------------------------------------- */
    
	void doKeyPressed(KeyEvent arg0) {
		switch(arg0.getKeyCode()) {
                case KeyEvent.VK_UP:
                	if(!lightMove) {
                		moveForward(0.1);
                        look(10);
                	} else {
                		Lights.light_position[lightSelected][1] += 0.1;
                	}
                    break;
                case KeyEvent.VK_DOWN:
                	if(!lightMove) {
                		moveForward(-0.1);
                        look(10);                        
                	} else {
                		Lights.light_position[lightSelected][1] -= 0.1;
                	}
                	break;
                case KeyEvent.VK_RIGHT:
                	if(!lightMove) {
                		strafeRight(0.1);
                        look(10);
                	} else {
                		Lights.light_position[lightSelected][0] -= 0.1;
                	}                    
                    break;
                case KeyEvent.VK_LEFT:
                	if(!lightMove) {
                		strafeLeft(0.1);
                        look(10);
                	} else {
                		Lights.light_position[lightSelected][0] += 0.1;
                	}                    
                    break;
                case KeyEvent.VK_B:
                	if(lightMove) {
                		Lights.light_position[lightSelected][2] -= 0.1;
                	}
                	break;
                case KeyEvent.VK_F:
                	if(lightMove) {
                		Lights.light_position[lightSelected][2] += 0.1;
                	}
                	break;
                case KeyEvent.VK_O: // on revient sur l'origine
                	init();
                    break;
                case KeyEvent.VK_M:
                    vueSolide = !vueSolide;
                    break;
                case KeyEvent.VK_T:
                    squelettemode = !squelettemode;
                    break;
                case KeyEvent.VK_P:
                	if(lightSelected != -1) {
                		lightMove = !lightMove;
                	} 
                	System.out.println("light move "+lightMove + " and selected "+lightSelected);
                	break;
                case KeyEvent.VK_L:
                	lightSelect = !lightSelect;
                	if(!lightSelect) {
                		lightMove = false; lightSelected = -1;
                	}
                	System.out.println("lightSelect is "+lightSelect);
                	break;
                case KeyEvent.VK_X:
                	activateLight = !activateLight; 
                	System.out.println("activate light is "+activateLight);
                	break;
                case KeyEvent.VK_1: treatKey(1);             	
                	break;
                case KeyEvent.VK_2: treatKey(2);
                	break;
                case KeyEvent.VK_3: treatKey(3);
                	break;
                case KeyEvent.VK_4: treatKey(4);
                	break;
                case KeyEvent.VK_5: treatKey(5);
                	break;
                case KeyEvent.VK_6: treatKey(6);
                	break;
                case KeyEvent.VK_7: treatKey(7);
                	break;
                case KeyEvent.VK_8: treatKey(8);
                	break;                
		}
	}
	
	public int getLightSelected() {
		return lightSelected;
	}

	private void treatKey(int i) {
		if(activateLight) {
    		Lights.activated[i - 1] = !Lights.activated[i - 1];
    		if(Lights.activated[i - 1]) {
    			Lights.light_position[i - 1][0] = mean(xLPos, xPos);
    			Lights.light_position[i - 1][1] = mean(yLPos, yPos);
    			Lights.light_position[i - 1][2] = mean(zLPos, zPos);
    		} else if(lightSelected == i - 1) {
    			lightMove = false; lightSelected = -1;
    		}
    	}
		if(lightSelect && Lights.activated[i - 1]) { lightSelected = i - 1; } 
		System.out.println("lumiere "+i+" active "+ Lights.activated[i - 1] +" light select "+ lightSelect +
				" light selected "+lightSelected);
	}
	
	private float mean(double posCenter, double posEye) {		
		double d = (4 * posEye / 5) + (posCenter / 5);
				
		return (float)d;
	}

	public void keyboardChecks(boolean[] keys)
	{
        if(keys['z'])
        {            
            moveForward(0.1);
            look(10);
        }
        
        if(keys['s'])
        {      
            moveForward(-0.1);
            look(10);
        }

        if(keys['j'])
        {
            pitchUp(0.05);
            look(10);
        }
        
        if(keys['k'])
        {
            pitchDown(0.05);
            look(10);
        }
        
        if(keys['a'])
        {
            yawLeft(0.01);
            look(10);
        }
        
        if(keys['e'])
        {
            yawRight(0.01);
            look(10);
        }
        
        if(keys['q'])
        {
            strafeLeft(0.1);
            look(10);
        }
        
        if(keys['d'])
        {
            strafeRight(0.1);
            look(10);
        }        
		
	}
    
}
